﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ExpLib.Core.Adapter;
using System.Threading;

namespace ExpLib.Service
{
    /// <summary>
    /// 用于定期执行某些个方法的类
    /// </summary>
    public class ScheduleService:IDisposable
    {

        /// <summary>
        /// 定时器
        /// </summary>
        Timer m_InnerTimer = null;
        /// <summary>
        /// 日志类
        /// </summary>
        ILogger m_Logger = null;

        /// <summary>
        /// 日历集合
        /// </summary>
        ISchedule[] m_Schedules = null;


        public ScheduleService(ILogger logger,params ISchedule[] calendars)
        {
            m_Logger = logger;

            m_Schedules = calendars;

        }
        

        public void OnStart()
        {
            m_InnerTimer = new Timer(new TimerCallback(this.InnerInterval), null, 0, 10000);
        }


        private void InnerInterval(Object state)
        {
            foreach (ISchedule scheulde in m_Schedules)
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(ExecueteTask), scheulde);
            }
        }

        /// <summary>
        /// 执行Task的Execute方法
        /// </summary>
        /// <param name="task"></param>
        private void ExecueteTask(Object objscheulde)
        {
            if (objscheulde == null || !(objscheulde is ISchedule))
            {
                throw new ArgumentException("objscheulde为空或没有实现ISchedule接口");
            }

            ISchedule schedule = objscheulde as ISchedule;
            try
            {
                lock (schedule) //同一个Schedule实例只能串行执行，所以只能Lock Schedule
                {
                    if (schedule.CanRun())
                    {
                        InvokeWithTimeout(schedule.Task);
                    }
                }

                
            }
            catch (TimeoutException)
            {
                try
                {
                    //如果超时，则调用OnTimeout方法
                    schedule.Task.OnTimeout();
                }
                catch { }

            }
            catch (Exception ex)
            {
                try
                {
                    //如果异常，则调用OnExrror
                    schedule.Task.OnError(ex);
                }
                catch { }
            }
        
        }


        /// <summary>
        /// 调用Task的Exccute,如果超时则退出
        /// </summary>
        /// <param name="task"></param>
        private void InvokeWithTimeout(ITask task)
        {

            Action apmInvokeDelegate = new Action(task.Excuete);
            IAsyncResult result = apmInvokeDelegate.BeginInvoke(null, null);
            if (((task.Timeout != -1) && !result.IsCompleted) && (!result.AsyncWaitHandle.WaitOne(task.Timeout, false) || !result.IsCompleted))
            {
                throw new TimeoutException("执行定时任务超时，超时时间:" + task.Timeout);
            }

            apmInvokeDelegate.EndInvoke(result);

        }


        public void Dispose()
        {
            foreach (ISchedule calendar in m_Schedules)
            {
                if (calendar.Task != null)
                {
                    try {
                        calendar.Task.Dispose();
                    }
                    catch { }
                }
            }

            m_Schedules = null;
        }
    }
}
